www.gusucode.com > VC++ 仿Winamp自动停靠窗体-源码程序 > VC++ 仿Winamp自动停靠窗体-源码程序/code/DockWnd/DockDlg.cpp

    //Download by http://www.NewXing.com
// DockDlg.cpp : implementation file
//

#include "stdafx.h"
#include "DockWnd.h"
#include "DockDlg.h"
#include "DockWndDlg.h"
#include "math.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CDockDlg dialog


CDockDlg::CDockDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CDockDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDockDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	m_nDirection = BOTTOM;
}


void CDockDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDockDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CDockDlg, CDialog)
	//{{AFX_MSG_MAP(CDockDlg)
	ON_WM_CLOSE()
	ON_WM_MOVING()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDockDlg message handlers

void CDockDlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
	CDockWndDlg *pWnd;
	pWnd = (CDockWndDlg *)this->FromHandle(m_hParent);
	pWnd->InverseState();
}

BOOL CDockDlg::Init(HWND hParent)
{
	m_hParent = hParent;
	return Create(IDD_DISPLAY,this->GetDesktopWindow());
}

// 定义两个域值
#define THRESHOLD 1
#define GAP 30
void CDockDlg::Dock(UINT nDirection,CWnd *pWndMain)
{
	// 得到主窗体矩形区域
	CRect rectMain;
	pWndMain->GetWindowRect(&rectMain);

	// 进行停靠操作
	m_nDirection = nDirection;

	if (nDirection == LEAVE)
		m_nDirection = NO_DIRECTION;

	// 不再停靠
	else if (!IsDocking(rectMain,m_rectWnd,nDirection))
		Dock(LEAVE,pWndMain);

	int nSep;
	switch (m_nDirection)
	{
	case LEFT:
		// 从左方停靠
		nSep = rectMain.left - m_rectWnd.right;
		if (abs(nSep) > THRESHOLD && abs(nSep) <= GAP)
		{
			m_rectWnd.OffsetRect(nSep,0);
			Dock(LEFT,pWndMain);
		}
		else if (abs(nSep) > GAP)
			Dock(LEAVE,pWndMain);
		break;
	case RIGHT:
		// 从右边停靠
		nSep = rectMain.right - m_rectWnd.left;
		if (abs(nSep) > THRESHOLD && abs(nSep) <= GAP)
		{
			m_rectWnd.OffsetRect(nSep,0);
			Dock(RIGHT,pWndMain);
		}
		else if (abs(nSep) > GAP)
			Dock(LEAVE,pWndMain);
		break;
	case TOP:
		// 从上边停靠
		nSep = rectMain.top - m_rectWnd.bottom;
		if (abs(nSep) > THRESHOLD && abs(nSep) <= GAP)
		{
			m_rectWnd.OffsetRect(0,nSep);
			Dock(TOP,pWndMain);
		}
		else if (abs(nSep) > GAP)
			Dock(LEAVE,pWndMain);
		break;
	case BOTTOM:
		// 从下面停靠
		nSep = rectMain.bottom - m_rectWnd.top;
		if (abs(nSep) > THRESHOLD && abs(nSep) <= GAP)
		{
			m_rectWnd.OffsetRect(0,nSep);
			Dock(BOTTOM,pWndMain);
		}
		else if (abs(nSep) > GAP)
			Dock(LEAVE,pWndMain);
		break;
	case NO_DIRECTION:
		// 子窗体未停靠
		break;
	case LEAVE:
		// 不再是停靠状态
		m_nDirection = NO_DIRECTION;
	}
}

UINT CDockDlg::GetDirection() const
{
	return m_nDirection;
}

BOOL CDockDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	// TODO: Add extra initialization here
	CWnd *pWnd;
	pWnd = this->FromHandle(m_hParent);

	// 得到主窗体矩形
	CRect rectMain;
	pWnd->GetWindowRect(&rectMain);

	// 获得自身矩形
	this->GetWindowRect(&m_rectWnd);

	// 左对齐
	m_rectWnd.right = rectMain.left + m_rectWnd.Width();
	m_rectWnd.left = rectMain.left;

	// 开始将子窗体停靠在主窗体的下方
	m_rectWnd.bottom = rectMain.bottom + m_rectWnd.Height();
	m_rectWnd.top = rectMain.bottom;
	this->MoveWindow(&m_rectWnd);
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CDockDlg::OnMoving(UINT fwSide, LPRECT pRect) 
{
	// TODO: Add your message handler code here
	// 得到自身矩形区域
	m_rectWnd.CopyRect(pRect);

	// 得到主窗体指针
	CWnd *pWnd;
	pWnd= this->FromHandle(m_hParent);

	Dock(m_nDirection,pWnd);
	*pRect = m_rectWnd;
}

BOOL CDockDlg::IsDocking(CRect &rectMain, CRect &rectMine, UINT nDirection)
{
	if (nDirection == LEFT || nDirection == RIGHT)
	{
		if (rectMine.top >= rectMain.top && rectMine.top <= rectMain.bottom)
			return TRUE;
		else if (rectMine.bottom >= rectMain.top && rectMine.bottom <= rectMain.bottom)
			return TRUE;
	}
	else if (nDirection == TOP || nDirection == BOTTOM)
	{
		if (rectMine.left >= rectMain.left && rectMine.left <= rectMain.right)
			return TRUE;
		else if (rectMine.right >= rectMain.left && rectMine.right <= rectMain.right)
			return TRUE;
	}
	else if (nDirection == NO_DIRECTION)
	{
		if ((rectMine.left < rectMain.right && rectMine.left > rectMain.left)
				|| (rectMine.right < rectMain.right && rectMine.right > rectMain.left))
		{
			if (abs(rectMine.top - rectMain.bottom) <= GAP)
			{
				m_nDirection = BOTTOM;
				return TRUE;
			}
			else if (abs(rectMine.bottom - rectMain.top) <= GAP)
			{
				m_nDirection = TOP;
				return TRUE;
			}
		}
		if ((rectMine.top < rectMain.bottom && rectMine.top > rectMain.top)
			|| (rectMine.bottom < rectMain.bottom && rectMine.bottom > rectMain.top))
		{
			if (abs(rectMine.left - rectMain.right) <= GAP)
			{
				m_nDirection = RIGHT;
				return TRUE;
			}
			else if (abs(rectMine.right - rectMain.left) <= GAP)
			{
				m_nDirection = LEFT;
				return TRUE;
			}
		}
	}
	// nDirection == LEAVE 或者不在停靠状态
	return FALSE;
}

CRect CDockDlg::GetRect() const
{
	return m_rectWnd;
}